/*
 *所有关于MaterialMaster类的业务代码应在此处编写
*可使用repository.调用常用方法，获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*MaterialMasterService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using Mercury.Core.BaseProvider;
using Mercury.Core.Extensions.AutofacManager;
using Mercury.Entity.DomainModels;
using System.Linq;
using Mercury.Core.Utilities;
using System.Linq.Expressions;
using Mercury.Core.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using Mercury.System.IRepositories;
using Mercury.Core.ManageUser;
using System.Reflection.Metadata.Ecma335;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using System.IO;
using System;
using System.Collections.Generic;
using OfficeOpenXml;
using System.Reflection;
using Mercury.System.IServices;
using Mercury.System.Repositories;
using System.Threading.Tasks;
using Mercury.Core.DBManager;
using System.Data.SqlClient;
using System.Data;
using EFCore.BulkExtensions;

namespace Mercury.System.Services
{
    public partial class MaterialMasterService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IMaterialMasterRepository _repository;//访问数据库    
        private readonly IBaseElementRepository _baseElementRepository;//访问数据库

        [ActivatorUtilitiesConstructor]
        public MaterialMasterService(
            IMaterialMasterRepository dbRepository,
            IHttpContextAccessor httpContextAccessor,
            IBaseElementRepository baseElementRepository
            )
        : base(dbRepository)
        {
            _baseElementRepository = baseElementRepository;
            _httpContextAccessor = httpContextAccessor;
            _repository = dbRepository;
            //多租户会用到这init代码，其他情况可以不用
            //base.Init(dbRepository);
        }


        public override WebResponseContent Update(SaveModel saveModel)
        {
            WebResponseContent webResponse = new WebResponseContent();
            base.UpdateOnExecute = (SaveModel userModel) =>
            {
                if (userModel.DetailData != null && userModel.DetailData.Any())
                {
                    var sum = 0m;
                    foreach (var item in userModel.DetailData)
                    {
                        var temp = 0m;
                        if (decimal.TryParse(item["Content"]?.ToString(), out temp))
                        {
                            sum += temp;
                            if (sum > 100)
                                return webResponse.Error("元素占比总和不能超过【100%】！");
                        }
                    }
                }
                return webResponse.OK();
            };
            return base.Update(saveModel);
        }

        public override WebResponseContent DownLoadTemplate()
        {
            string tableName = typeof(T).GetEntityTableCnName();
            string dicPath = $"Download/{DateTime.Now.ToString("yyyMMdd")}/Template/".MapPath();
            if (!Directory.Exists(dicPath)) Directory.CreateDirectory(dicPath);
            string fileName = tableName + DateTime.Now.ToString("yyyyMMddHHssmm") + ".xlsx";
            EPPlusHelper.Export<MaterialMaster>(null, null, GetIgnoreTemplate(typeof(MaterialMaster)), dicPath, fileName, true, new Dictionary<string, bool>() {
                { "元素成分/占比",true}
            });
            return Response.OK(null, dicPath + fileName);
        }

        public override WebResponseContent Import(List<IFormFile> files)
        {
            if (files == null || files.Count == 0)
                return Response.Error("请选择上传的文件");
            Microsoft.AspNetCore.Http.IFormFile formFile = files[0];
            string dicPath = $"Upload/{DateTime.Now.ToString("yyyMMdd")}/{typeof(T).Name}/".MapPath();
            if (!Directory.Exists(dicPath)) Directory.CreateDirectory(dicPath);
            dicPath = $"{dicPath}{Guid.NewGuid().ToString()}_{formFile.FileName}";

            using (var stream = new FileStream(dicPath, FileMode.Create))
            {
                formFile.CopyTo(stream);
            }


            FileInfo file = new FileInfo(dicPath);
            if (!file.Exists) return Response.Error("未找到上传的文件,请重新上传");

            var entities = new List<MaterialMaster>();
            var details = new List<MaterialElement>();
            var elements = new List<BaseElement>();
            var existsMaterial = new List<string>();
            var user = UserContext.Current.UserInfo;
            using (ExcelPackage package = new ExcelPackage(file))
            {
                if (package.Workbook.Worksheets.Count == 0 ||
                    package.Workbook.Worksheets.FirstOrDefault().Dimension.End.Row <= 1)
                    return Response.Error("未导入数据");

                var baseElement = _baseElementRepository.FindAsync(c => true).Result;
                ExcelWorksheet sheet = package.Workbook.Worksheets.FirstOrDefault();
                for (int m = sheet.Dimension.Start.Row + 1, n = sheet.Dimension.End.Row; m <= n; m++)
                {
                    var entity = new MaterialMaster()
                    {
                        CreateDate = DateTime.Now,
                        CreateUserId = user.User_Id.ToString(),
                        CreateUserName = user.UserName,
                        ModifyUserId = user.User_Id.ToString(),
                        ModifyDate = DateTime.Now,
                        ModifyUserName = user.UserName
                    };
                    entity.Name = sheet.Cells[m, 2].Value?.ToString();
                    entity.MaterialNo = sheet.Cells[m, 3].Value?.ToString();
                    var exists = repository.ExistsAsync(c => c.MaterialNo == entity.MaterialNo).Result;
                    if (exists)
                    {
                        existsMaterial.Add(entity.Name);
                        continue;
                    }
                    entity.Id = Guid.NewGuid().ToString();
                    _ = int.TryParse(sheet.Cells[m, 4].Value?.ToString(), out int category);
                    entity.Category = category;
                    entity.InspectionItems = sheet.Cells[m, 5].Value?.ToString();
                    _ = int.TryParse(sheet.Cells[m, 6].Value?.ToString(), out int enable);
                    entity.Enable = 0;
                    _ = int.TryParse(sheet.Cells[m, 7].Value?.ToString(), out int deleted);
                    entity.DeletionFlag = deleted;
                    var detailStr = sheet.Cells[m, 8].Value?.ToString();
                    entities.Add(entity);
                    if (!string.IsNullOrEmpty(detailStr))
                    {
                        var arr = detailStr.Split(',');
                        var sum = 0m;
                        foreach (var item in arr)
                        {
                            var tempStr = item.Split('|');
                            var elementSymbols = tempStr[0];
                            var rate = tempStr[1];
                            var element = baseElement.FirstOrDefault(c => c.ElementSymbols == elementSymbols);
                            if (element == null && !elements.Any(c => c.ElementSymbols == elementSymbols))
                            {
                                element = new BaseElement()
                                {
                                    Id = Guid.NewGuid().ToString(),
                                    ElementName = elementSymbols,
                                    ElementSymbols = elementSymbols,
                                    CreateDate = DateTime.Now,
                                    CreateUserName = "系统生成",
                                    DeletionFlag = 0
                                };
                                elements.Add(element);
                            }
                            _ = decimal.TryParse(rate, out decimal content);
                            details.Add(new MaterialElement()
                            {
                                Id = Guid.NewGuid().ToString(),
                                MaterialId = entity.Id,
                                ElementId = element.Id,
                                ElementName = element.ElementName,
                                ElementSymbols = elementSymbols,
                                Content = content,
                                CreateDate = DateTime.Now,
                                Enable = 1,
                                DeletionFlag = 0
                            });

                            sum += content;
                        }

                        if (sum > 1)
                        {
                            details = details.Where(c => c.MaterialId != entity.Id).ToList();
                            entities.Remove(entity);
                        }
                    }
                }

                var result = -1;
                repository.DapperContext.BeginTransaction(dapper =>
                {
                    if (entities.Any())
                    {
                        result = dapper.AddRange(entities);
                        if (result <= 0)
                            return false;
                    }

                    if (details.Any())
                    {
                        result = dapper.AddRange(details);
                        if (result <= 0)
                            return false;
                    }

                    if (elements.Any())
                    {
                        result = dapper.AddRange(elements);
                        if (result <= 0)
                            return false;
                    }
                    return true;
                }, e => { });
            }
            var existsMsg = string.Empty;
            if (existsMaterial.Any())
            {
                existsMsg = $"{existsMaterial.Take(5).Aggregate((c, t) => c + "," + t)}{(existsMsg.Count() > 5 ? "..." : "")}等已存在，已忽略！";
            }
            var msg = $"保存成功!{existsMsg}";
            return Response.OK(msg);
        }

        private DataTable ToTable(List<MaterialMaster> entities)
        {
            DataTable queueTable = CreateEmptyDataTable();
            foreach (var entity in entities)
            {
                DataRow row = queueTable.NewRow();
                row["Id"] = entity.Id;
                row["Name"] = entity.Name;
                row["MaterialNo"] = entity.MaterialNo;
                row["Category"] = entity.Category;
                row["InspectionItems"] = entity.InspectionItems;
                row["Enable"] = entity.Enable;
                row["CreateUserName"] = entity.CreateUserName;
                row["CreateUserId"] = entity.CreateUserId;
                row["CreateDate"] = entity.CreateDate;
                row["ModifyUserName"] = entity.ModifyUserName;
                row["ModifyUserId"] = entity.ModifyUserId;
                row["ModifyDate"] = entity.ModifyDate;
                row["DeletionFlag"] = entity.DeletionFlag;

                queueTable.Rows.Add(row);
            }
            return queueTable;
        }
        private DataTable CreateEmptyDataTable()
        {
            DataTable queueTable = new DataTable();
            queueTable.Columns.Add("Id", typeof(string));
            queueTable.Columns.Add("Name", typeof(string));
            queueTable.Columns.Add("MaterialNo", typeof(string));
            queueTable.Columns.Add("Category", Type.GetType("System.Int32"));
            queueTable.Columns.Add("InspectionItems", typeof(string));
            queueTable.Columns.Add("Enable", Type.GetType("System.Int32"));
            queueTable.Columns.Add("CreateUserName", typeof(string));
            queueTable.Columns.Add("CreateUserId", typeof(string));
            queueTable.Columns.Add("CreateDate", Type.GetType("System.DateTime"));
            queueTable.Columns.Add("ModifyUserName", typeof(string));
            queueTable.Columns.Add("ModifyUserId", typeof(string));
            queueTable.Columns.Add("ModifyDate", Type.GetType("System.DateTime"));
            queueTable.Columns.Add("DeletionFlag", Type.GetType("System.Int32"));

            return queueTable;
        }


    }
}
